/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.brillien.kernel.axiom;

import com.vii.brillien.kernel.BrillienException;
import com.vii.brillien.kernel.axiom.component.State;
import com.vii.brillien.kernel.axiom.component.StateDivision;

import java.util.Collection;

/**
 * Brillien represents the probelms of real world as a free communications' flow. Components have 3 roles basically: start, receive communication and alter during communications
 * This interface define all state management behaviors which belongs to altering part of its roles.
 * Every components has a logical state codomain describing the possible being state. It' logical level, responsible to add an abstraction layer to the communication flow, like coloring in dataflow languages. 
 * Multiple states could be present simultaneously. The amount of multiple state is defined ridigly and in unchangeably way,
 * so a specific component has allways n state independently the vitality of a state in a specific communication.
 * The static state list means a list of locks technically, and the behavior of a component should be devided by these locks to ensure the maximum effectivity regarding its processes.
 * So the lock are some kind of dusjunct variables and the states are the possible value range. * As the component uses several lock just the affected behaviors are locked, other behaviors could flow smoothly.
 * By default, every Progressor define 3 built-in lock: CALLABLE_LOCK_INDEX, SERVICES_LOCK_INDEX, DEFAULT_LOCK.
 * The CALLABLE_LOCK is responsible for the state collecting all Sensor behaviors, last lock in the list
 * The SERVICES_LOCK is responsible for the state collecting all Aspirer behaviors, last lock in the list before the CALLABLE_LOCK 
 * The DEFAULT_LOCK is responsible for the state collecting all other behaviors, first lock in the list of locks
 * Another feature: every state altering could indicate new communication flows via the built-in notification system. Every Progressor take registration regarding a specific state flow and make notifications to the registered listeners in case of that altering
 */
public interface Progressor {

    /**
     * @return Decides whether this component has states acting as a definite state machine
     */
    boolean                         hasStateMachine();

    /**
     * Initializes the state space of a Progressor
     */
    void                            initStateMashine();

    /**
     * Gets all potential states of a specific component
     */
    <T extends State> Collection<T> getPotentialStates();

    /**
     * Tells whether this component's state space is convenient for a given scope or not
     */
    boolean                         isInValidStates();

    /**
     * Tells whether the given component's state space contains only exit states or not
     */
    boolean                         isInExitState();

    /**
     * Tells whether the given component's state space contains the given state or not
     */
    boolean                         isInState( State state );

    /**
     * Gets actual states; the list size is equal to locks' count and contains the "state" of the locks.
     */
    <T extends State> Collection<T> getActualStates();

    /**
     * Gets the StateDivision object to check the validity of all state transitions
     */
    StateDivision                   getStateDivision();

    /**
     * Sets the StateDivision object to check the validity of all state transitions
     * @param stateDivision StateDevision object
     */
    void                            setStateDivision( StateDivision stateDivision );

    /**
     * Induces internal state change.
     * @param from actual state to be changed
     * @param to new state
     * @throws BrillienException in any case of error
     */
    void                            changeState( State from, State to ) throws BrillienException;

    /**
     * Adds a new State into the statemachine
     * @throws BrillienException in any case of error
     */
    void                            addState( State state ) throws BrillienException;

    /**
     * Removes a State from the statemachine
     * @throws BrillienException in any case of error
     */
    void                            removeState( State state ) throws BrillienException;

    /**
     * Any Sensor object can register to a specific state modification
     * @param state the state to be listened
     * @param recipient the entity who need to notified when a notification would be sent induced by a state change
     * @throws BrillienException in any error case LogicException is thrown
     */
    void                            registerStateChangeNotification(State state, String recipient) throws BrillienException;

    /**
     * Any Sensor object can unregister from a specific state altering takes place
     * @param state the state to be listened
     * @param recipient the entity who need to notified when a notification would be sent induced by a state change
     * @throws BrillienException in any error case LogicException is thrown
     */
    void                            unregisterStateChangeNotification(State state, String recipient ) throws BrillienException;

    /**
     * Makes this Progressor to panic. This adds ERROR-type State to its statespace.
     * @param message cause of the panic
     */
    void                            panic( String message );

}
